package com.ella.common.security.filter;
import com.alibaba.fastjson2.JSONObject;
import com.ella.entity.security.LoginUser;
import com.ella.utils.JwtUtil;
import com.ella.utils.RedisCache;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * 在请求到controller层之前先到jwt过滤器这一层
 *  JWT过滤器( 过滤器)=> 当用户在登录之后在每个页面之间跳转时，都会携带token(在请求后台服务器时),每次的请求都会被这个过滤器拦截进行验证
 *  包括权限校验
 *  这里我有必要解释一下: redis服务中存放了完整的LoginUser(包含User,权限,userid,ip....)
 *  而token中仅仅存放的是userid,权限
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

	@Resource
	private RedisCache redisCache;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

		String token = request.getHeader("token");
		//判断是否为空
		if (StringUtils.isEmpty(token)  || token.equals("null")){
			// TODO 为什么没有携带token要放行
			filterChain.doFilter(request, response);
			return;
		}
		//判断是否过期
		LoginUser loginUser = JwtUtil.parseJWT(token);
		//刷新token
		//JwtUtil.verifyToken(loginUser);

		//TODO 封装Authentication对象(包括用户的基本信息 及其 权限信息)存入SecurityContextHolder
	    loginUser.getPermissions().add("ROLE_admin");
		UsernamePasswordAuthenticationToken authenticationToken =
				new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
		/**
		 * SecurityContextHolder底层默认用的是 static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal();
		 * 这么一个本地线程，还有 new InheritableThreadLocal() , static SecurityContext contextHolder这两种方式
		 */
		SecurityContextHolder.getContext().setAuthentication(authenticationToken);
		filterChain.doFilter(request, response);

	}

		/*
		 如果token为空从redis获取
		 if (loginUser == null){
			//从redis中获取用户信息
			String redisKey = RedisConstants.LOGIN_USER_INFO_STORE_PRE+loginUser.getUser().getUserId();
			Object cacheObject = redisCache.getCacheObject(redisKey);
			String loginUser_jsonString = String.valueOf(cacheObject);
			LoginUser redisLoginUser = JSONObject.parseObject(loginUser_jsonString, LoginUser.class);
			if (Objects.isNull(redisLoginUser)){
				throw new RuntimeException("用户未登录");
			}
		}*/

}